﻿using CoreBluetooth;
using Foundation;
using MauiControl.Models;
using MauiControl.Services;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace MauiControl.Platforms.MacCatalyst.Services
{
    public class BluetoothServiceMacCatalyst : IBluetoothService, IDisposable
    {
        public static class Uuids
        {
            public const string Service = "ae30"; // 使用短格式 UUID
            public const string Write = "ae01";   // 使用短格式 UUID
            public const string Notify = "ae02";  // 使用短格式 UUID

            public const string GenericAccess = "1800"; // 使用短格式 UUID
            public const string DeviceName = "2a00";    // 使用短格式 UUID
            public const string BatteryService = "180f"; // 使用短格式 UUID
            public const string BatteryLevel = "2a19";   // 使用短格式 UUID
        }

        private CBCentralManager _centralManager;
        private List<BleDeviceInfo> _devices;
        private TaskCompletionSource<List<BleDeviceInfo>> _searchCompletionSource;
        private Action<BleDeviceInfo> _onDeviceAddedCallback;
        private readonly Dictionary<string, CBPeripheral> _discoveredDevices = new();

        private CBPeripheral _connectedPeripheral;
        private CBCharacteristic _receiveCharacteristic;
        private CBCharacteristic _sendCharacteristic;
        private bool _isConnected = false;
        private object _lockObject = new object();
        private bool _disposed = false;
        public event EventHandler<byte[]> DataReceived;

        public BluetoothServiceMacCatalyst()
        {
            _devices = new List<BleDeviceInfo>();
            _centralManager = new CBCentralManager();

            _centralManager.UpdatedState += OnUpdatedState;
            _centralManager.DiscoveredPeripheral += OnDiscoveredPeripheral;
            _centralManager.ConnectedPeripheral += OnConnectedPeripheral;
            _centralManager.DisconnectedPeripheral += OnDisconnectedPeripheral;

            Debug.WriteLine("CBCentralManager 已初始化，事件已绑定。");
        }

        public async Task<List<BleDeviceInfo>> SearchDevicesAsync(CancellationToken cancellationToken, Action<BleDeviceInfo> onDeviceAddedCallback)
        {
            _devices.Clear();
            _discoveredDevices.Clear();

            _searchCompletionSource = new TaskCompletionSource<List<BleDeviceInfo>>();
            _onDeviceAddedCallback = onDeviceAddedCallback;

            Debug.WriteLine("开始扫描蓝牙设备...");
            Debug.WriteLine($"蓝牙状态: {_centralManager.State}");

            _centralManager.ScanForPeripherals(new CBUUID[0]); // 扫描所有设备
            Debug.WriteLine("扫描已启动。");

            try
            {
                Debug.WriteLine("等待扫描完成...");
                await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken);

                Debug.WriteLine("扫描完成，停止扫描。");
                _centralManager.StopScan();

                if (_devices.Count == 0)
                {
                    Debug.WriteLine("未找到任何设备。");
                }
                else
                {
                    Debug.WriteLine($"找到 {_devices.Count} 个设备。");
                }

                return _devices;
            }
            catch (TaskCanceledException)
            {
                Debug.WriteLine("扫描任务被取消。");
                _centralManager.StopScan();
                return new List<BleDeviceInfo>();
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"设备搜索失败: {ex.Message}");
                _centralManager.StopScan();
                throw new Exception($"设备搜索失败: {ex.Message}");
            }
        }

        private void OnDiscoveredPeripheral(object sender, CBDiscoveredPeripheralEventArgs e)
        {
            var deviceName = e.Peripheral.Name ?? "未知设备";
            var deviceId = e.Peripheral.Identifier.ToString(); // 使用 UUID 作为设备标识符
            Debug.WriteLine($"发现设备: {deviceName} (ID: {deviceId})");

            var device = new BleDeviceInfo(
                name: deviceName,
                address: deviceId, // 使用 UUID 作为设备地址
                macAddress: deviceId, // 使用 UUID 作为 MAC 地址
                platformSpecificId: deviceId // 使用 UUID 作为平台特定标识符
            );

            if (!_discoveredDevices.ContainsKey(deviceId))
            {
                Debug.WriteLine($"发现设备: {deviceName} (ID: {deviceId})");
                _discoveredDevices[deviceId] = e.Peripheral;
                _devices.Add(device); // 将设备添加到 _devices 列表
                _onDeviceAddedCallback?.Invoke(device);
            }
        }

        private void OnUpdatedState(object sender, EventArgs e)
        {
            Debug.WriteLine($"蓝牙状态更新: {_centralManager.State}");
            if (_centralManager.State == CBManagerState.PoweredOn)
            {
                Debug.WriteLine("蓝牙已打开，可以开始扫描设备。");
            }
            else
            {
                Debug.WriteLine("蓝牙未打开或不可用。");
            }
        }

        public async Task<BleDeviceInfo> ConnectDeviceAsync(string deviceId)
        {
            int retryCount = 6;
            for (int i = 0; i < retryCount; i++)
            {
                try
                {
                    Debug.WriteLine($"尝试连接设备，设备ID: {deviceId} (尝试次数: {i + 1})");

                    if (!_discoveredDevices.ContainsKey(deviceId))
                    {
                        throw new KeyNotFoundException($"未找到地址为 {deviceId} 的设备。");
                    }

                    var peripheral = _discoveredDevices[deviceId];

                    // 检查 peripheral 是否已被释放
                    if (peripheral == null || peripheral.Handle == IntPtr.Zero)
                    {
                        Debug.WriteLine("CBPeripheral 对象已被释放，尝试重新获取设备。");
                        if (_discoveredDevices.ContainsKey(deviceId))
                        {
                            peripheral = _discoveredDevices[deviceId];
                        }
                        else
                        {
                            throw new Exception("无法重新获取设备。");
                        }
                    }

                    // 增加延迟，确保设备名称已经初始化
                    await Task.Delay(1000);

                    if (string.IsNullOrEmpty(peripheral.Name))
                    {
                        Debug.WriteLine("设备名称为空，可能设备未正确初始化。");
                        // 使用设备ID作为替代名称
                        var deviceName = $"Device-{deviceId}";
                        Debug.WriteLine($"使用替代设备名称: {deviceName}");
                    }
                    else
                    {
                        Debug.WriteLine($"设备名称: {peripheral.Name}");
                    }

                    // 断开之前的连接
                    if (_connectedPeripheral != null && _connectedPeripheral.State == CBPeripheralState.Connected)
                    {
                        Disconnect();
                    }

                    _connectedPeripheral = peripheral;
                    _centralManager.ConnectPeripheral(_connectedPeripheral);

                    await Task.Delay(2000);

                    Debug.WriteLine($"设备连接状态: {_connectedPeripheral.State}");

                    // 检查连接状态
                    if (_connectedPeripheral.State != CBPeripheralState.Connected)
                    {
                        throw new Exception("设备未成功连接。");
                    }

                    // 发现服务和特征
                    await DiscoverServicesAndCharacteristicsAsync();

                    // 启用通知
                    await EnableNotificationAsync();

                    // 读取电量信息
                    string batteryLevel = await GetBatteryLevelAsync(deviceId);

                    return new BleDeviceInfo(peripheral.Name ?? $"Device-{deviceId}", deviceId, deviceId, deviceId)
                    {
                        BatteryLevel = batteryLevel // 更新电量信息
                    };
                }
                catch (Exception ex)
                {
                    Debug.WriteLine($"连接设备时出错: {ex.Message}");
                    if (i == retryCount - 1)
                    {
                        throw;
                    }
                    await Task.Delay(1000);
                }
            }

            throw new Exception("多次尝试后仍无法连接设备。");
        }

        private async Task DiscoverServicesAndCharacteristicsAsync()
        {
            // 检查设备连接状态
            if (_connectedPeripheral.State != CBPeripheralState.Connected)
            {
                Debug.WriteLine("设备未连接，无法发现服务。");
                throw new Exception("设备未连接。");
            }

            // 发现服务
            _connectedPeripheral.DiscoverServices(new CBUUID[] { CBUUID.FromString(Uuids.Service) });

            // 增加延迟，确保服务发现完成
            await Task.Delay(2000);

            // 打印所有服务 UUID
            if (_connectedPeripheral.Services != null)
            {
                foreach (var service in _connectedPeripheral.Services)
                {
                    Debug.WriteLine($"发现服务: {service.UUID}");
                }
            }

            // 查找目标服务
            var targetService = _connectedPeripheral.Services?.FirstOrDefault(s =>
            {
                // 将服务 UUID 转换为字符串并去掉连字符
                var serviceUuid = s.UUID.ToString().ToLower().Replace("-", "");
                var targetUuid = Uuids.Service.ToLower().Replace("-", "");

                // 直接匹配短格式 UUID
                return serviceUuid == targetUuid;
            });

            if (targetService == null)
            {
                Debug.WriteLine("未找到目标服务。");
                throw new Exception("未找到目标服务。");
            }

            // 发现特征
            _connectedPeripheral.DiscoverCharacteristics(new CBUUID[]
            {
        CBUUID.FromString(Uuids.Write),  // 写入特征 (ae01)
        CBUUID.FromString(Uuids.Notify)  // 读取特征 (ae02)
            }, targetService);

            await Task.Delay(1000);

            // 查找写入特征 (ae01)
            _sendCharacteristic = targetService.Characteristics?.FirstOrDefault(c =>
            {
                // 将特征 UUID 转换为字符串并去掉连字符
                var characteristicUuid = c.UUID.ToString().ToLower().Replace("-", "");
                var targetUuid = Uuids.Write.ToLower().Replace("-", "");

                // 直接匹配短格式 UUID
                return characteristicUuid == targetUuid;
            });

            if (_sendCharacteristic == null)
            {
                Debug.WriteLine("未找到写入特征 (ae01)。");
                throw new Exception("未找到写入特征 (ae01)。");
            }

            // 查找读取特征 (ae02)
            _receiveCharacteristic = targetService.Characteristics?.FirstOrDefault(c =>
            {
                // 将特征 UUID 转换为字符串并去掉连字符
                var characteristicUuid = c.UUID.ToString().ToLower().Replace("-", "");
                var targetUuid = Uuids.Notify.ToLower().Replace("-", "");

                // 直接匹配短格式 UUID
                return characteristicUuid == targetUuid;
            });

            if (_receiveCharacteristic == null)
            {
                Debug.WriteLine("未找到读取特征 (ae02)。");
                throw new Exception("未找到读取特征 (ae02)。");
            }

            // 打印特征值的 UUID 和属性
            Debug.WriteLine($"找到写入特征: {_sendCharacteristic.UUID}, 属性: {_sendCharacteristic.Properties}");
            Debug.WriteLine($"找到读取特征: {_receiveCharacteristic.UUID}, 属性: {_receiveCharacteristic.Properties}");
        }

        private async Task EnableNotificationAsync()
        {
            try
            {
                // 确保设备连接
                await EnsureConnectedAsync();

                // 检查特征是否初始化
                if (_receiveCharacteristic == null)
                {
                    Debug.WriteLine("接收特征未初始化，尝试重新发现特征。");
                    await DiscoverServicesAndCharacteristicsAsync();
                }

                // 启用通知
                _connectedPeripheral.SetNotifyValue(true, _receiveCharacteristic);
                await Task.Delay(500);

                Debug.WriteLine($"通知已启用，特征 UUID: {_receiveCharacteristic.UUID}");
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"启用通知时出错: {ex.Message}");
                throw;
            }
        }

        public async Task<byte[]> ReadRawDataAsync()
        {
            try
            {
                // 确保设备连接
                await EnsureConnectedAsync();

                // 检查读取特征是否初始化
                if (_receiveCharacteristic == null)
                {
                    Debug.WriteLine("读取特征未初始化，尝试重新发现特征。");
                    await DiscoverServicesAndCharacteristicsAsync();
                }

                // 读取数据
                _connectedPeripheral.ReadValue(_receiveCharacteristic);
                //await Task.Delay(500);

                var rawData = _receiveCharacteristic.Value?.ToArray();
                if (rawData == null)
                {
                    throw new Exception("读取到的数据为空。");
                }

                Debug.WriteLine($"读取到的原始数据: {BitConverter.ToString(rawData)}");
                Debug.WriteLine($"数据读取成功，特征 UUID: {_receiveCharacteristic.UUID}");
                return rawData;
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"读取数据时出错: {ex.Message}");
                throw;
            }
        }

        public async Task WriteDataAsync(byte[] data)
        {
            try
            {
                // 确保设备连接
                await EnsureConnectedAsync();

                // 检查写入特征是否初始化
                if (_sendCharacteristic == null)
                {
                    Debug.WriteLine("写入特征未初始化，尝试重新发现特征。");
                    await DiscoverServicesAndCharacteristicsAsync();
                }

                // 打印要写入的数据
                Debug.WriteLine($"准备写入的数据: {BitConverter.ToString(data)}");

                // 发送数据
                _connectedPeripheral.WriteValue(NSData.FromArray(data), _sendCharacteristic, CBCharacteristicWriteType.WithoutResponse);
                await Task.Delay(500);

                Debug.WriteLine($"数据写入成功，特征 UUID: {_sendCharacteristic.UUID}");
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"写入数据时出错: {ex.Message}");
                throw;
            }
        }

        private async Task EnsureConnectedAsync()
        {
            if (_connectedPeripheral == null || _connectedPeripheral.State != CBPeripheralState.Connected)
            {
                Debug.WriteLine("设备未连接，尝试重新连接。");
                await ConnectDeviceAsync(_connectedPeripheral.Identifier.ToString());
            }
        }

        public void Disconnect()
        {
            lock (_lockObject)
            {
                if (!_isConnected || _disposed) return;
                _isConnected = false;
            }

            try
            {
                if (_connectedPeripheral != null)
                {
                    _centralManager.CancelPeripheralConnection(_connectedPeripheral);
                    _connectedPeripheral.Dispose();
                    _connectedPeripheral = null;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"断开连接时出错: {ex.Message}");
            }
        }

        private void OnConnectedPeripheral(object sender, CBPeripheralEventArgs e)
        {
            Debug.WriteLine("设备已连接。");
            _isConnected = true;
        }

        private void OnDisconnectedPeripheral(object sender, CBPeripheralErrorEventArgs e)
        {
            Debug.WriteLine($"设备已断开连接。错误: {e.Error?.LocalizedDescription}");
            Disconnect();
        }

        public void Dispose()
        {
            lock (_lockObject)
            {
                if (_disposed) return;
                _disposed = true;

                if (_connectedPeripheral != null)
                {
                    _connectedPeripheral.Dispose();
                    _connectedPeripheral = null; // 确保对象被释放后设置为 null
                }

                if (_centralManager != null)
                {
                    _centralManager.DiscoveredPeripheral -= OnDiscoveredPeripheral;
                    _centralManager.UpdatedState -= OnUpdatedState;
                    _centralManager.ConnectedPeripheral -= OnConnectedPeripheral;
                    _centralManager.DisconnectedPeripheral -= OnDisconnectedPeripheral;
                    _centralManager.Dispose();
                    _centralManager = null;
                }
            }
        }

        /// <summary>
        /// 获取电池电量
        /// </summary>
        /// <param name="deviceId"></param>
        /// <returns></returns>
        public async Task<string> GetBatteryLevelAsync(string deviceId)
        {
            try
            {
                var batteryServiceUuid = CBUUID.FromString(Uuids.BatteryService);
                var batteryLevelCharacteristicUuid = CBUUID.FromString(Uuids.BatteryLevel);

                Debug.WriteLine("开始获取电池服务...");

                // 发现电池服务
                _connectedPeripheral.DiscoverServices(new CBUUID[] { batteryServiceUuid });
                await Task.Delay(1000); // 等待服务发现完成

                var batteryService = _connectedPeripheral.Services?.FirstOrDefault(s => s.UUID == batteryServiceUuid);
                if (batteryService == null)
                {
                    Debug.WriteLine("未找到电池服务。");
                    return "N/A";
                }

                Debug.WriteLine("电池服务已找到，开始获取电量特征...");

                // 发现电量特征
                _connectedPeripheral.DiscoverCharacteristics(new CBUUID[] { batteryLevelCharacteristicUuid }, batteryService);
                await Task.Delay(1000); // 等待特征发现完成

                var batteryLevelCharacteristic = batteryService.Characteristics?.FirstOrDefault(c => c.UUID == batteryLevelCharacteristicUuid);
                if (batteryLevelCharacteristic == null)
                {
                    Debug.WriteLine("未找到电量特征。");
                    return "N/A";
                }

                Debug.WriteLine("电量特征已找到，开始读取电量值...");

                // 读取电量值
                _connectedPeripheral.ReadValue(batteryLevelCharacteristic);
                await Task.Delay(500); // 等待数据读取完成

                if (batteryLevelCharacteristic.Value == null)
                {
                    Debug.WriteLine("读取到的电量值为空。");
                    return "N/A";
                }

                var batteryLevel = batteryLevelCharacteristic.Value[0];
                Debug.WriteLine($"读取到的电量值: {batteryLevel}%");
                return $"{batteryLevel}%";
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"读取电量信息时出错: {ex.Message}");
                return "N/A";
            }
        }
    }
}